home *** CD-ROM | disk | FTP | other *** search
/ Informática Multimedia 1995 April / Informatica Multimedia CD - Epimundo.iso / DOS / FILEFIND / FFF / PROCZIP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-08  |  6.3 KB  |  200 lines

  1. /***************************************************************************
  2.  *                                                                         *
  3.  * ZIP Processing Functions                                                *
  4.  * These routines are used to process files with the ZIP entension.        *
  5.  **************************************************************************/
  6.  
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10.  
  11. #undef MAIN
  12.  
  13. #include "fff.h"
  14. #include "zip.h"
  15. #include "queue.h"
  16.  
  17. int Match (char *Str, char *Pat);
  18. void PrtVerbose (char *Path, char *Name, DOS_FILE_TIME *Time, DOS_FILE_DATE *Date,
  19.                  long Size);
  20. void ChkPage (void);
  21. int  SearchQ (char *Str);
  22.  
  23. /***********************************************************************
  24.  * DoZip is the main routine to process an entire ZIP file             *
  25.  ***********************************************************************/
  26.  
  27.  void
  28. DoZip (char *Name) {
  29.     FILE *ZIPFile;
  30.  
  31.     if ( (ZIPFile = fopen(Name, "rb")) == NULL ) {
  32.         fprintf(stderr, "%s", Name);
  33.         perror("");
  34.         }
  35.     ProcessHeaders(ZIPFile, Name);
  36.     fclose(ZIPFile);
  37.     }
  38.  
  39. /***********************************************************************
  40.  * Unlike the other PC-based archivers, PKZip produces files that have *
  41.  * both a distributed directory and a central directory.  For programs *
  42.  * such as FFF which are not interested in the content of the files in *
  43.  * the ZIP but in their directory data, a great deal of time can be    *
  44.  * saved by processing the central directory rather than reading the   *
  45.  * entire file just to find the entries in the distributed directory!  *
  46.  * The central directory of a ZIP file is located at the "back end" of *
  47.  * the file, however, finding it it slightly complicate by the fact    *
  48.  * the file may have a variable number of non-relevant characters      *
  49.  * appended by some of the file transfer protocols (one main-frame     *
  50.  * Kermit protocol can append as many as 1,440 non-relevant characters *
  51.  ***********************************************************************/
  52.  
  53.  void
  54. ProcessHeaders (FILE *ZIPFile, char *Path) {
  55.     extern int TotalMatch, VerboseSwt, CaseSwt, Spaced, PageSwt;
  56.     extern char V_Name[14];
  57.     extern char V_Path[66];
  58.     extern ARC_TYPE ArcType;
  59.     extern int Lnno;
  60.     extern S[6][3];
  61.  
  62.     int i, Printed, Index, ZipLen;
  63.     long FileLen;
  64.     char *Buffer, *Name, *p;
  65.     char DireName[65];
  66.     unsigned Count;
  67.     long Offset, S_Offset, Block;
  68.     unsigned long *Ptr;
  69.     unsigned long CentralSig;
  70.     END_CENTRAL_DIRECTORY_RECORD *EndPtr;
  71.     CENTRAL_DIRECTORY_FILE_HEADER *CentralHeader;
  72.  
  73. /*----------------------------------------------------------------------*/
  74. /* Establish the buffer to search the "back end" of the file.            */
  75. /* SEARCH_SIZE (#defined in zip.h) establishes the buffer size and        */
  76. /* should be no less than 1024 bytes.  I have found 2048 to be a little    */
  77. /* more sure.                                                            */
  78.  
  79.     if ( (Buffer = malloc(SEARCH_SIZE)) == NULL) {
  80.         fprintf(stderr, "Insufficient memory!\n");
  81.         exit(1);
  82.         }
  83.  
  84. /* Position to the end of the ZIP file and get the file size in bytes    */
  85.  
  86.     fseek(ZIPFile, 0L, SEEK_END);
  87.     FileLen = ftell(ZIPFile);
  88.  
  89. /* Reset the ZIP file position to the beginning of the file                */
  90.  
  91.     fseek(ZIPFile, 0L, SEEK_SET);
  92.     if (FileLen < SEARCH_SIZE) {
  93.         ZipLen = fread(Buffer, (size_t) 1, (size_t) FileLen, ZIPFile);
  94.         }
  95.     else {
  96.         fseek(ZIPFile, (long) -SEARCH_SIZE, SEEK_END);
  97.         ZipLen = fread(Buffer, 1, SEARCH_SIZE, ZIPFile);
  98.         }
  99.  
  100. /* Search backwards for the "End of Central Directory" entry            */
  101.  
  102.     for (i = ZipLen - 4; i >= 0; --i) {
  103.         Ptr = (unsigned long *) &Buffer[i];
  104.         if (*Ptr == END_CENTRAL_DIR_SIGNATURE) break;
  105.         }
  106.     if (i < 0) {
  107.         fprintf(stderr, "%s: Invalid ZIP format\n", Path);
  108.         fprintf(stderr, "      - No \"End-of-Central-Directory\" record!\n");
  109.         free(Buffer);
  110.         return;
  111.         }
  112.  
  113. /* The "End of Central Directory" entry contains the count of the entries    */
  114. /* and the offset of the first entry in the Central Directory                */
  115.  
  116.     EndPtr = (END_CENTRAL_DIRECTORY_RECORD *) &Buffer[i + 4];
  117.     Count = EndPtr->CentralDirEntries_ThisDisk;
  118.     S_Offset = Offset = EndPtr->OffsetStartCentralDirectory;
  119.  
  120. /* This may be a problem with VERY large ZIPs!  If the length of the         */
  121. /* Central Directory exceeds 64K, this will NOT work!                        */
  122.  
  123.     Block = FileLen - Offset;
  124.     free(Buffer);
  125.  
  126. /* Read the entire Central Directory into memory and process each entry    */
  127.  
  128.     Buffer = malloc( (size_t) Block);
  129.     fseek(ZIPFile, S_Offset, SEEK_SET);
  130.     fread(Buffer, (size_t) 1, (size_t) Block, ZIPFile);
  131.     Printed = 0;
  132.     for (Index = i = 0; i < Count; ++i) {
  133.         ++S[ArcType][1];
  134.         memmove(&CentralSig, &Buffer[Index], 4);
  135.         if (CentralSig != CENTRAL_FILE_HEADER_SIGNATURE) {
  136.             fprintf(stderr, "%s: Invalid ZIP format\n", Path);
  137.             fprintf(stderr, "     - bad \"Central Directory\" record!\n");
  138.             free(Buffer);
  139.             return;
  140.             }
  141.         Index += 4;
  142.         CentralHeader = (CENTRAL_DIRECTORY_FILE_HEADER *) &Buffer[Index];
  143.         Index += sizeof(CENTRAL_DIRECTORY_FILE_HEADER);
  144.         Name = malloc(CentralHeader->FileNameLength + 1);
  145.         memmove(Name, &Buffer[Index], CentralHeader->FileNameLength);
  146.         Name[CentralHeader->FileNameLength] = '\0';
  147.         Index += CentralHeader->FileNameLength
  148.                 + CentralHeader->FileCommentLength
  149.                 + CentralHeader->ExtraFieldLength;
  150.         if ( (p = strrchr(Name, '/')) != NULL) {
  151.             *p = '\0';
  152.             strcpy(DireName, Name); strcat(DireName, "/");
  153.             ++p;
  154.             }
  155.         else {
  156.             DireName[0] = '\0';
  157.             p = Name;
  158.             }
  159.         if ( SearchQ(p) ) {
  160.             ++S[ArcType][2];
  161.             ++TotalMatch;
  162.             if (PageSwt) ChkPage();
  163.             strcpy(V_Name, p);
  164.             strcpy(V_Path, Path);
  165.             if (CaseSwt == ON) {
  166.                 strlwr(V_Name);
  167.                 strlwr(V_Path);
  168.                 strlwr(DireName);
  169.                 }
  170.             if (VerboseSwt) {
  171.                 if (!Printed) {
  172.                     if (!Spaced) {
  173.                         if (PageSwt) ChkPage();
  174.                         printf("\n");
  175.                         ++Lnno;
  176.                         }
  177.                     if (PageSwt) ChkPage();
  178.                     printf("%s\n", V_Path);
  179.                     ++Lnno;
  180.                     Printed = 1;
  181.                     }
  182.                 fputs("* ", stdout);
  183.                 PrtVerbose(DireName, V_Name, &CentralHeader->LastModFileTime,
  184.                            &CentralHeader->LastModFileDate,
  185.                            CentralHeader->UncompressedSize);
  186.                 }
  187.             else printf("%s--> (%s/%s)\n", V_Path, DireName, V_Name);
  188.             ++Lnno;
  189.             }
  190.         free(Name);
  191.         }
  192.     free(Buffer);
  193.     if (Printed) {
  194.         if (PageSwt) ChkPage();
  195.         printf("\n");
  196.         ++Lnno;
  197.         Spaced = 1;
  198.         }
  199.     }
  200.